package com.wstuo.multitenancy;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;

import org.hibernate.HibernateException;
import org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
import org.hibernate.service.jdbc.connections.spi.MultiTenantConnectionProvider;
import org.hibernate.service.spi.Configurable;
import org.hibernate.service.spi.ServiceRegistryAwareService;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.service.spi.Stoppable;
import org.springframework.context.ApplicationContext;

import com.wstuo.common.security.utils.AppContext;
import com.wstuo.common.util.AppliactionBaseListener;

/**
 * 根据 tenantIdentifier 获得相应的连接
 * @author will
 *
 */
@SuppressWarnings("serial")
public class SchemaBasedMultiTenantConnectionProvider 
implements MultiTenantConnectionProvider, Stoppable,Configurable, ServiceRegistryAwareService {
	
	private DriverManagerConnectionProviderImpl connectionProvider=ConnectionProviderBuilder.buildConnectionProvider();

	public Connection getAnyConnection() throws SQLException {
		final Connection connection = connectionProvider.getConnection();
		return connection;
	}

	public void releaseAnyConnection(Connection connection) throws SQLException {
		connectionProvider.closeConnection(connection);
	}
	
	public Connection getConnection(String tenantIdentifier) throws SQLException {
		final Connection connection = getAnyConnection();
		try {
	        connection.createStatement().execute( "USE " + tenantIdentifier );
	    }catch ( SQLException e ) {
	    	if(connection!=null){
	    		connectionProvider.closeConnection( connection );
	    	}
	    	clearSession();
	        throw new HibernateException("Could not alter JDBC connection to specified schema [" +
	                            tenantIdentifier + "]",e);
	    }
	    return connection;
	}
	
	public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException {
		try {
	          connection.createStatement().execute( "USE "+tenantIdentifier);
	    }catch ( SQLException e ) {
	          throw new HibernateException("Could not alter JDBC connection to specified schema [" +
	                            tenantIdentifier + "]",e);
	    }
		connectionProvider.closeConnection( connection );
	}
	
	private void clearSession(){
		ApplicationContext ctx =AppliactionBaseListener.ctx;
		if(ctx!=null){
			//Session
			AppContext appctx = (AppContext)ctx.getBean("appctx");
			if(appctx!=null){
				appctx.setAttribute("tenantId", null);
			}
		}
	}

	public boolean isUnwrappableAs(Class arg0) {
		// TODO Auto-generated method stub
		return false;
	}

	public Object unwrap(Class arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	public void injectServices(ServiceRegistryImplementor arg0) {
		// TODO Auto-generated method stub
		
	}

	public void configure(Map arg0) {
		// TODO Auto-generated method stub
		
	}

	public void stop() {
		// TODO Auto-generated method stub
		
	}

	

	public boolean supportsAggressiveRelease() {
		// TODO Auto-generated method stub
		return false;
	}
}
